
/* <<< COPYRIGHT START >>>
 * Copyright 2006-Present OxygenSoftwareLibrary.com
 * Licensed under the GNU Lesser General Public License.
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * @author: Ugorji Dick-Nwoke
 * <<< COPYRIGHT END >>>
 */


package oxygen.tool.wlfacade;

import java.util.ArrayList;
import java.util.Collection;

import javax.management.ObjectName;

import weblogic.management.WebLogicObjectName;

public class WLJMXHandler {
  private static String sep = "=";
  private static String sep2 = "@";
  
  public String getStringRep(ObjectName wlmbean, Object mbs, boolean recurse) throws Exception {
    StringBuffer buf = new StringBuffer();
    getStringRepRec0(wlmbean, mbs, buf, recurse);
    return buf.toString();
  }
  
  public String getRelativeStringRep(ObjectName wlmbean, Object mbs) throws Exception {
    String strrep = getStringRep(wlmbean, mbs, false);
    if(strrep.length() > 0) {
      strrep = strrep.substring(1);
    }
    return strrep;
  }
  
  public ObjectName getParent(ObjectName oname, Object mbs) throws Exception {
    if(oname == null) {
      throw new NullPointerException("Within getParent: oname is null");
    } else if(oname instanceof WebLogicObjectName) {
      return ((WebLogicObjectName)oname).getParent();
    } else if(oname instanceof ObjectName) {
      //do this check, so that we trim the number of places we have to check for the parent attribute
      try {
        //System.out.print("+"); System.out.flush();
        WebLogicObjectName woname = new WebLogicObjectName(oname.toString());
        //only true root mbeans are returned here
        if(woname.getType() != null && woname.getName() != null) {
          WebLogicObjectName wlobjpar = woname.getParent();
          //System.out.println("WebLogicObjectName: cmo: " + oname + "wlobjpar: " + wlobjpar);
          //if(wlobjpar == null || (oname.getKeyProperty("Parent") != null)) {
          //  return wlobjpar;
          //}
          
          //           if(wlobjpar == null) {
          //             return wlobjpar;
          //           } else {
          //             String type0 = wlobjpar.getType();
          //             //the algorithm is bogus here ... it sometimes parents the wrong object
          //             if(!("DomainConfig".equals(type0) || "Domain".equals(type0))) {
          //               return wlobjpar;
          //             }
          //           }
          return wlobjpar;
        }
      } catch(Exception exc) { }
      
      //now try and decipher again what the children are here
      //do this funky check, 'cos WLS says that the mbean is WebLogicMBean, but it is ObjectName

      // COMMENT THIS OUT FOR NOW (till WLS bug is fixed)
      //       try {
      //         //System.out.print("-"); System.out.flush();
      //         Object wlobjparmb = WLScriptHelper.mbs_getAttribute(mbs, oname, "Parent");
      //         if(wlobjparmb != null) {
      //           if(wlobjparmb instanceof ObjectName) {
      //             return (ObjectName)wlobjparmb;
      //           } else if(wlobjparmb instanceof WebLogicMBean) {
      //             return ((WebLogicMBean)wlobjparmb).getObjectName();
      //           }
      //         }
      //       } catch(AttributeNotFoundException atnfe) { }

    } 
    //return null; 
    //if we still can't figure it out, assume it is orphaned.
    //return new ObjectName("orphaned:Name=orphaned");
    //System.out.print("*"); System.out.flush();
    return null; 
  }

  public ObjectName getLookupPattern(String domain, String stringrep) throws Exception {
    TypeName tn = getTypeName(stringrep);
    StringBuffer buf = new StringBuffer();
    if(domain == null) {
      buf.append("*");
    } else {
      buf.append(domain);
    }
    buf.append(":");
    if(tn.type != null) {
      buf.append("Type=").append(tn.type).append(",");
    }
    if(tn.name != null) {
      buf.append("Name=").append(tn.name).append(",");
    }
    if(tn.location != null) {
      buf.append("Location=").append(tn.location).append(",");
    }
    buf.append("*");
    //System.out.println("objectname pattern: " + buf);
    //System.out.println("parentobjname: " + parentobjname);
    //System.out.println("parentobjname(map): " + parentobjname.getKeyPropertyList());
    ObjectName oname = new ObjectName(buf.toString());
    //System.out.println("getLookupPattern(): " + oname);
    return oname;
  }
  
  // do not use split, because a sep in the value will cause problems
  public TypeName getTypeName(String stringrep) {
    String[] ra = WLScriptHelper.twoElemSplit(stringrep, sep);
    if(ra[0] == null) {
      return null;
    } else if(ra[1] == null) {
      return new TypeName(null, ra[0], null);
    } else {
      String[] ra2 = WLScriptHelper.twoElemSplit(ra[1], sep2);
      return new TypeName(ra[0], ra2[0], ra2[1]);
    }
  }
  
  public String getStringRepGivenTypeName(TypeName tn) {
    StringBuffer buf = new StringBuffer();
    if(tn.type != null) {
      buf.append(tn.type).append(sep);
    }
    if(tn.name != null) {
      buf.append(tn.name);
    }
    if(tn.location != null) {
      buf.append(sep2).append(tn.location);
    }
    return buf.toString();
  }
  
  private void getStringRepRec0(ObjectName wlmbean, Object mbs, StringBuffer buf, boolean recurse) 
    throws Exception {
    if(wlmbean == null) {
      return;
    }
    ObjectName wlmparent = getParent(wlmbean, mbs);
    if(recurse) {
      getStringRepRec0(wlmparent, mbs, buf, recurse);
    }
    buf.append("/");
    String type0 = wlmbean.getKeyProperty("Type");
    if(type0 != null) {
      buf.append(type0).append(sep);
    }
    buf.append(wlmbean.getKeyProperty("Name"));
    String location0 = wlmbean.getKeyProperty("Location");
    if(location0 != null) {
      buf.append(sep2).append(location0);
    }
  }

  /**
   * Tries to trim the returned objectnames, so that we only return the ones which
   * match the stringrep requested.
   * E.g. if string rep does not define Type and Location, we should only return
   * objectnames without type and location in them
   *
   * This is really important when we search for mbeans where 2 objectnames exist, 
   * but some are only valid on a given server
   */
  public ObjectName[] trim(ObjectName[] onames, String domain, String stringrep) {
    Collection col = new ArrayList();
    TypeName typename = getTypeName(stringrep);
    for(int i = 0; i < onames.length; i++) { 
      if(typename.location == null) {
        String location = onames[i].getKeyProperty("Location");
        if(location == null) {
          col.add(onames[i]);
        }
      } else if(typename.type == null) {
        String type = onames[i].getKeyProperty("Type");
        if(type == null) {
          col.add(onames[i]);
        }
      } else {
        col.add(onames[i]);
      }
    }
    onames = (ObjectName[])col.toArray(new ObjectName[0]);
    return onames;
  }

  public static class TypeName {
    public String type;
    public String name;
    public String location;
    
    public TypeName(String type, String name, String location) {
      this.type = type;
      this.name = name;
      this.location = location;
    }
  }
}

